package cn.twh.wall.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
public class ControllerLogAspect {
    /**
     * 切点表达式: ..两个点表明多个,*代表一个 表达式代表切入com..service包下的所有类的所有方法,方法参数不限,返回类型不限。
     * 其中访问修饰符可以不写,不能用*,第一个*代表返回类型不限,第二个*表示所有类,第三个*表示所有方法,..两个点表示方法里的参数不限。
     */
    private final String POINT_CUT = "execution(* cn..controller.*.*(..))";

    /**
     * 命名切点 public 切点可访问性修饰符 与类可访问性修饰符的功能是相同的,它可以决定定义的切点可以在哪些类中可使用.pointCut 切点名称
     * void 返回类型
     * <p>
     * 因为命名切点仅利用方法名及访问修饰符的信息, 一般定义方法的返回类型为 void,并且方法体为空
     */
    @Pointcut(POINT_CUT)
    public void pointCut() {
    }

    /**
     * 在切点方法之前执行
     *
     * @param joinPoint 接入点
     */
    @Before(value = "pointCut()")
    public void doBefore(JoinPoint joinPoint) {
        log.debug("挡板接入成功");
    }

    /**
     * 在切点方法之后执行
     *
     * @param joinPoint 接入点
     */
    @After(value = "pointCut()")
    public void doAfter(JoinPoint joinPoint) {
        log.debug("挡板接出成功");
    }

    /**
     * 切点方法返回后执行 如果第一个参数为JoinPoint,则第二个参数为返回值的信息
     * 如果第一个参数不为JoinPoint,则第一个参数为returning中对应的参数
     * returning：限定了只有目标方法返回值与通知方法参数类型匹配时才能执行后置返回通知,否则不执行, 参数为Object类型将匹配任何目标返回值
     *
     * @param joinPoint 接入点
     * @param result    切入方法的返回
     */
    @AfterReturning(value = "pointCut()", returning = "result")
    public void doAfter(JoinPoint joinPoint, Object result) {
        log.debug("挡板接出成功:" + result);
    }

}
